import { DataRegister } from './../../../../../models/data-register';
import { EventManagerService } from './../../../../../services/event-manager.service';
import { BaseService } from './../../../../../services/base.service';
import { AfterViewInit, Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { NzMessageService, NzModalService, NzUploadFile } from 'ng-zorro-antd';
import { ExceptionHandler } from 'src/app/handler/exception.handler';
import { DataRegisterService } from 'src/app/services';
import { EngineService } from '../../../services/engine.service';
import { BaseFieldComponent } from '../base-field/base-field.component';
import { PermitConfig, PermitConfigId } from '../../../models';
import { Subscription } from 'rxjs';
import { WorkflowPageService } from 'src/app/common/page-render/workflow-page-container/workflow-page.service';
import { DataChangeLogService } from 'src/app/services/data-change-log.service';
import { FlowNode } from 'src/app/models/work-flow';
import { UploadService } from 'src/app/services/upload.service';

@Component({
  selector: 'zepride-base-table',
  templateUrl: './base-table.component.html',
  styleUrls: ['./base-table.component.less', '../field.common.less']
})
export class BaseTableComponent extends BaseFieldComponent implements OnInit, AfterViewInit, OnDestroy {

  queryParams = {
    pageIndex: 1,
    countOfPage: 10,
    total: 0
  };
  loading = false;
  dataSource: { dataType: string; objectId: string; objectType: string; };
  dataList = [];
  eventId: string;
  export$: Subscription;
  workflowUpdatedSub: Subscription;
  dataRegister: DataRegister;
  flowNode: {
    flowNodeId: string;
    nodeName: string;
    status: string;
    updateTime: number;
    flowNode: FlowNode;
  };
  dataChangeLogUpdatedSub: Subscription;
  flowNodeUpdateSub: Subscription;

  uploadUrl = '';

  permitConfig: PermitConfig[] = [
    { mode: 'query', permitId: '查看', permitName: '', authObjectId: '' },
    { mode: 'edit', permitId: '编辑', permitName: '', authObjectId: '' },
    { mode: 'edit', permitId: '删除', permitName: '', authObjectId: '' }
  ];

  canEdit = true;
  canDelete = true;
  fileType = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  uploading = false;

  constructor(
    protected engineService: EngineService,
    private router: Router,
    private modalService: NzModalService,
    protected dataRegisterService: DataRegisterService,
    private message: NzMessageService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    private workflowPageService: WorkflowPageService,
    protected dataChangeLogSvr: DataChangeLogService,
    public uploadService: UploadService,
  ) {
    super(engineService, baseSvr, eventSvr, null, uploadService, message, dataRegisterService);
  }

  get bindData() {
    const bindField = this.componentData.bindField;
    if (this.dataModel && bindField) {
      return this.dataModel[bindField];
    } else {
      return this.componentData.defaultValue;
    }
  }

  ngOnInit() {
    this.dataRegister = null;
    this.queryParams.countOfPage = this.componentData.extends && this.componentData.extends.countOfPage ? this.componentData.extends.countOfPage : 10;
    this.workflowUpdatedSub = this.workflowPageService.workflowUpdated.subscribe(dataRegister => {
      if (!dataRegister) {
        return;
      }

      this.dataRegister = dataRegister;
    });

    this.flowNodeUpdateSub = this.workflowPageService.flowNodeUpdate.subscribe(data => {
      if (!data) {
        return;
      }
      this.flowNode = data;
    });

    this.dataChangeLogUpdatedSub = this.dataChangeLogSvr.dataChangeLogUpdated$.subscribe(data => {
      this.getData();
    });
  }

  async ngAfterViewInit() {
    await this.getDataSourceById();
    this.getData();
    this.eventId = this.eventSvr.registEvent('search-bar.onQuery.' + this.componentData.tmpComItemId, (args) => {
      const p = {} as any;
      for (const item of args.queryList) {
        if (item.valueBegin || item.valueEnd) {
          p[item.bindField + '.beginTime'] = new Date(item.valueBegin).getTime();
          p[item.bindField + '.endTime'] = new Date(item.valueEnd).getTime();
        } else {
          if (item.ctrlType === 'flowNode') {
            item.bindField = 'curNodeNames';
          }
          if (item.ctrlType === 'flowStatus') {
            item.bindField = 'status';
          }
          if (item.value) {
            p[item.bindField] = item.value;
          }
        }
      }
      this.getData(false, p);
    });
    this.registerTableExport();

    setTimeout(() => {
      const authData = this.setAuthorityData();
      this.zeprideAuthorityData = {
        ...authData,
        afterChecked: this.afterAuthChecked.bind(this)
      };
    });
  }

  setBindData(value: any) {
    const bindField = this.componentData.bindField;
    if (bindField) {
      value.forEach((element: any) => {
        delete element.children;
      });
      this.dataModel[bindField] = value;
      this.engineService.dataModelChange$.next({
        bindField,
        value,
        identifyId: this.componentData.identifyId,
        tmpComItemId: this.tmpComItemId,
        dataModel: this.dataModel
      });
    }
  }
  /**
   * 表格数据的相关操作事件
   * @param type 事件类型
   * @param data 对应的数据
   * @param index 数据的下标
   */
  tableEvent(type: 'view' | 'edit' | 'delete', data: any, index?: number) {
    switch (type) {
      case 'view':
        this.editOrViewTableItem(data, 'view');
        break;
      case 'edit':
        this.editOrViewTableItem(data);
        break;
      case 'delete':
        this.modalService.confirm({
          nzTitle: '提示',
          nzContent: '确认删除？',
          nzOnOk: async () => {
            try {
              await this.dataRegisterService.deleteDataRegister(data.id);
              this.dataList.splice(index, 1);
              this.dataList = [...this.dataList];
              this.getData();
              this.message.success('删除成功！');
            } catch (error) {
              ExceptionHandler.current.handleError(error);
            }
          }
        });
        break;
    }
  }
  /**
   * 编辑操作
   * @param data 对应的数据
   */
  async editOrViewTableItem(data: any, mode = 'edit') {
    try {
      let dataRegisterId = data.id;
      let isChildDataRegister = false;
      const result = await this.dataRegisterService.getDataRegister(dataRegisterId);
      let dataRegister = result;
      if (result && result.parentDataRegisterId) {
        dataRegister = await this.dataRegisterService.getDataRegister(result.parentDataRegisterId);
        dataRegisterId = dataRegister.id;
        isChildDataRegister = true;
        this.workflowPageService.currentChildDataRegisterId = data.id;
      }
      const dataType = dataRegister.dataType;
      if (dataType && dataType === 'workflowOrder') {
        const workflowId = dataRegister.data.workflowId;
        let executingNode = dataRegister.data.flowNodesItems.find((node: { status: string; }) => node.status === 'process');
        if (dataRegister.status == 'complete') {
          executingNode = dataRegister.data.flowNodesItems[0];
        }
        const executingNodeId = executingNode.flowNodeId;
        this.router.navigate(['home/page/workflow-page', workflowId, executingNodeId], {
          queryParams: { dataRegisterId, mode },
          skipLocationChange: isChildDataRegister
        });
      } else {
        if (this.componentData.extends && this.componentData.extends.pageId) {
          const pageId = this.componentData.extends.pageId;
          this.dataRegisterService.tempDataRegisterId = data.id;
          this.router.navigate(['home/page/normal-page', pageId], {
            queryParams: { dataRegisterId, mode }
          });
        } else {
          this.message.error('表格未关联对应的页面');
        }
      }
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  async getData(isReset = false, p?) {
    try {
      if (isReset) {
        this.queryParams.pageIndex = 1;
      }
      const params = this.getParams();
      if (!params || !params.dataType) {
        return;
      }
      this.loading = true;
      const newParams = {
        ...params,
        ...p
      };
      if (this.dataSource && this.dataSource.objectType && this.dataSource.objectType === 'childrenWorkflow') {
        newParams.parentDataRegisterId = this.workflowPageService.currentDataRegisterId;
      } else {
        if (this.dataRegister) {
          newParams.dataRegisterId = this.dataRegister.id;
        }
        if (this.flowNode) {
          newParams.flowNodeId = this.flowNode.flowNodeId;
        }
      }

      delete newParams.total;
      const data: { list: any[], total: number } = await this.dataRegisterService.getComponentData(newParams);
      this.dataList = data.list ? data.list : [];

      this.queryParams.total = data.total ? data.total : 0;

      if (this.dataSource.dataType == 'dataChangeLog') {
        // 表示是变更记录的数据源 发出通知
        this.dataChangeLogSvr.dataChangeLogCountChanged$.next(this.queryParams.total);
      }
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    } finally {
      this.loading = false;
    }
  }

  getParams() {
    let params: any = {};
    params = {
      dataType: this.dataSource && this.dataSource.dataType ? this.dataSource.dataType : '',
      objectId: this.dataSource && this.dataSource.objectId ? this.dataSource.objectId : '',
      ...this.queryParams
    };
    return params;
  }

  private async getDataSourceById() {
    this.dataSource = await this.dataRegisterService.getDataSourceById(this.componentData.dataSource);
    this.uploadUrl = `${this.baseSvr.remoteAddress}/api/dataRegister/import?objectId=${this.dataSource.objectId}&objectType=${this.dataSource.objectType}&dataType=${this.dataSource.dataType}`;
  }

  registerTableExport() {
    this.export$ = this.eventSvr.export$.subscribe(params => {
      this.exportTableData(params);
    });
  }

  async exportTableData(params: any) {
    try {
      const headers = this.getTableHeaders();
      const requestParams = this.getExportParams(params);
      const queryParams = requestParams;
      const result = await this.dataRegisterService.exportData({
        body: headers,
        queryParams
      });
      const a = document.createElement('a');
      a.href = window.URL.createObjectURL(result);
      a.download = `${this.componentData.labelText}.xlsx`;
      a.style.display = 'none';
      document.body.appendChild(a);
      a.click();
      a.remove();
    } catch (error) {
      ExceptionHandler.current.handleError(error);
    }
  }

  getExportParams(params: { bindComTmpId: any; queryList: { value: any; bindField: string | number; }[]; }) {
    let queryParams = '';
    const result = [];
    params.queryList.forEach((item: { value: any; bindField: string | number; }) => {
      if (item.value) {
        const str = `${item.bindField}=${item.value}`;
        result.push(str);
      }
    });
    const dataType = this.dataSource && this.dataSource.dataType ? this.dataSource.dataType : '';
    const objectId = this.dataSource && this.dataSource.objectId ? this.dataSource.objectId : '';
    result.push(`dataType=${dataType}`);
    result.push(`objectId=${objectId}`);
    queryParams = result.join('&');
    return queryParams;
  }

  getTableHeaders() {
    const fields = this.componentData.extends.fields;
    return fields.map((field: { name: any; bindField: any; }) => {
      return {
        name: field.name,
        bindField: field.bindField
      };
    });
  }

  pageSavedHandle = async () => {
    this.generateOutputHtml();
    // return null;
  }

  generateOutputHtml() {
    if (!this.componentData.bindField) {
      return;
    }
    const tableHeader: string[] = [];
    if (!this.componentData.extends.serialNoType) {
      tableHeader.push(`<th nzAlign="center">序号</th>`);
    }
    for (const item of this.componentData.extends.fields) {
      if (!item.isOutput) { continue; }
      tableHeader.push(`<th nzAlign="center">${item.name}</th>`);
    }
    const tableBody: string[] = [];
    for (let i = 0; i < this.dataList.length; i++) {
      const row = [];
      if (!this.componentData.extends.serialNoType) {
        row.push(`<td>${(i + 1) + ''}</td>`);
      }

      const rowItem = this.dataList[i];
      // tslint:disable-next-line: prefer-for-of
      for (let j = 0; j < this.componentData.extends.fields.length; j++) {
        const rowDataItem = this.componentData.extends.fields[j];
        if (!rowDataItem.isOutput) { continue; }
        const data = rowItem[rowDataItem.bindField];
        row.push(`<td>${data}</td>`);
      }

      tableBody.push('<tr>' + row.join('') + '</tr>');
    }

    const dataTableHtml = `<table>
      <thead>
        <tr>${tableHeader.join('')}</tr>
      </thead>
      <tbody>
        ${tableBody.join('')}
      </tbody>
    </table>`;

    this.dataModel[this.componentData.bindField + 'html'] = dataTableHtml;
  }

  afterAuthChecked(params: { permitId: PermitConfigId, isAuthorized: boolean }) {
    if (!params.isAuthorized) {
      if (params.permitId === '编辑') {
        this.canEdit = false;
      }
      if (params.permitId === '删除') {
        this.canDelete = false;
      }
    }
  }

  ngOnDestroy() {
    this.eventSvr.removeEvent(this.eventId);
    if (this.export$) {
      this.export$.unsubscribe();
    }
    if (this.workflowUpdatedSub) {
      this.workflowUpdatedSub.unsubscribe();
    }
    if (this.dataChangeLogUpdatedSub) {
      this.dataChangeLogUpdatedSub.unsubscribe();
    }

    this.dataRegister = null;
  }

  async readStart(item, index: number) {
    const readTxts = [];
    if (this.componentData.extends.serialNoType) {
      readTxts.push(`序号，${index + 1}`);
    }

    for (const field of this.componentData.extends.fields) {
      readTxts.push(`${field.name}，${item[field.bindField]}`);
    }

    for (const txt of readTxts) {
      await this.speak(txt);
    }
  }

  readStop() {
    speechSynthesis.cancel();
  }

  speak(readTxt) {
    return new Promise<void>((resolve, reject) => {
      const utterance = new SpeechSynthesisUtterance(readTxt);
      speechSynthesis.speak(utterance);
      utterance.onend = () => {
        resolve();
      };
    });
  }

  handleChange(info: { file: NzUploadFile }) {
    switch (info.file.status) {
      case 'uploading':
        this.uploading = true;
        break;
      case 'done':
        this.getBase64(info.file.originFileObj, (img: string) => {
          this.uploading = false;
          this.msg.success(`${info.file.name} 上传成功！`);
          location.reload();
        });
        break;
      case 'error':
        this.msg.error('Network error');
        this.uploading = false;
        break;
    }
  }

  private getBase64(img: File, callback: (img: string) => void) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result.toString()));
    reader.readAsDataURL(img);
  }


}
